const mimeMap = require('./mimeMap.js');
function FormData() {
    let fileManager = uni.getFileSystemManager();
    let data = {};
    let files = [];
    this.append = (name, value) => {
        data[name] = value;
        return true;
    };
    this.appendFile = (name, path, fileName) => {
        let buffer = fileManager.readFileSync(path);
        if (Object.prototype.toString.call(buffer).indexOf('ArrayBuffer') < 0) {
            return false;
        }
        if (!fileName) {
            fileName = getFileNameFromPath(path);
        }
        files.push({
            name: name,
            buffer: buffer,
            fileName: fileName
        });
        return true;
    };
    this.getData = () => convert(data, files);
}
function getFileNameFromPath(path) {
    let idx = path.lastIndexOf('/');
    return path.substr(idx + 1);
}
function convert(data, files) {
    let boundaryKey = 'wxmpFormBoundary' + randString(); // 数据分割符，一般是随机的字符串
    let boundary = '--' + boundaryKey;
    let endBoundary = boundary + '--';
    let postArray = [];
    //拼接参数
    if (data && Object.prototype.toString.call(data) == '[object Object]') {
        for (let key in data) {
            postArray = postArray.concat(formDataArray(boundary, key, data[key]));
        }
    }
    //拼接文件
    if (files && Object.prototype.toString.call(files) == '[object Array]') {
        for (let i in files) {
            let file = files[i];
            postArray = postArray.concat(formDataArray(boundary, file.name, file.buffer, file.fileName));
        }
    }
    //结尾
    let endBoundaryArray = [];
    endBoundaryArray.push(...endBoundary.toUtf8Bytes());
    postArray = postArray.concat(endBoundaryArray);
    return {
        contentType: 'multipart/form-data; boundary=' + boundaryKey,
        buffer: new Uint8Array(postArray).buffer
    };
}
function randString() {
    var result = '';
    var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    for (var i = 17; i > 0; --i) {
        result += chars[Math.floor(Math.random() * chars.length)];
    }
    return result;
}
function formDataArray(boundary, name, value, fileName) {
    let dataString = '';
    let isFile = !!fileName;
    dataString += boundary + '\r\n';
    dataString += 'Content-Disposition: form-data; name="' + name + '"';
    if (isFile) {
        dataString += '; filename="' + fileName + '"' + '\r\n';
        dataString += 'Content-Type: ' + getFileMime(fileName) + '\r\n\r\n';
    } else {
        dataString += '\r\n\r\n';
        dataString += value;
    }
    var dataArray = [];
    dataArray.push(...dataString.toUtf8Bytes());
    if (isFile) {
        let fileArray = new Uint8Array(value);
        dataArray = dataArray.concat(Array.prototype.slice.call(fileArray));
    }
    dataArray.push(...'\r'.toUtf8Bytes());
    dataArray.push(...'\n'.toUtf8Bytes());
    return dataArray;
}
function getFileMime(fileName) {
    let idx = fileName.lastIndexOf('.');
    let mime = mimeMap[fileName.substr(idx)];
    return mime ? mime : 'application/octet-stream';
}
String.prototype.toUtf8Bytes = function () {
    var that = this;
    var bytes = [];
    for (var i = 0; i < that.length; i++) {
        bytes.push(...that.utf8CodeAt(i));
        if (that.codePointAt(i) > 65535) {
            i++;
        }
    }
    return bytes;
};
String.prototype.utf8CodeAt = function (i) {
    var that = this;
    var out = [];
    var p = 0;
    var c = that.charCodeAt(i);
    if (c < 128) {
        out[p++] = c;
    } else if (c < 2048) {
        out[p++] = (c >> 6) | 192;
        out[p++] = (c & 63) | 128;
    } else if ((c & 64512) == 55296 && i + 1 < that.length && (that.charCodeAt(i + 1) & 64512) == 56320) {
        // Surrogate Pair
        c = 65536 + ((c & 1023) << 10) + (that.charCodeAt(++i) & 1023);
        out[p++] = (c >> 18) | 240;
        out[p++] = ((c >> 12) & 63) | 128;
        out[p++] = ((c >> 6) & 63) | 128;
        out[p++] = (c & 63) | 128;
    } else {
        out[p++] = (c >> 12) | 224;
        out[p++] = ((c >> 6) & 63) | 128;
        out[p++] = (c & 63) | 128;
    }
    return out;
};
module.exports = FormData;
